<template>
	<view class="wrap">
		<!-- 搜索框 -->
		<view class="search" @click="go()">
			<view class="searchInput">
				<u-icon name="search" color="#909399" :size="26"></u-icon>
				<text class="inpuTxt">请输入搜索关键词</text>
			</view>
		</view>
		<!-- 加载效果 -->
		<block v-if="status == 'loading'">
			<u-loadmore :status="status"></u-loadmore>
		</block>
		<!--滚动区域 -->
		<!-- 滚动区域 -->
		<view v-else-if="status == 'nomore'" class="menuwrap">
			<!-- 左侧滚动区域：纵向滚动：开启滑动的动画效果  -->
			<scroll-view scroll-y scroll-with-animation class="leftNav" :scroll-top="scrollTop">
				<view v-for="(item,index) in navList" :key="item.name" class="tabItem" @tap.stop="toggleMenu(index)">
					<text :class="['line',currentIndex==index ? 'active':'']">{{item.name}}</text>
				</view>
			</scroll-view>

			<!-- 右侧滚动区域：纵向滚动，开启滑动的动画效果 -->
			<scroll-view scroll-y scroll-with-animation class="rightNav" :scroll-top="scrollRightTop"
				@scroll="rightScroll">
				<view class="pageView">
					<view class="section" v-for="(item,index) in navList" :key="item.name" :id="'item'+index">
						<view class="title">
							<text>{{item.name}}</text>
						</view>
						<view class="aside">
							<!-- key不可重复 -->
							<view class="li" v-for="(val,i) in item.foods" :key="i">
								<image class="li-img" :src="val.icon"></image>
								<view class="li-name">{{val.name}}</view>
							</view>
						</view>
					</view>
				</view>
			</scroll-view>
		</view>


	</view>
</template>

<script>
	import {
		apiClassfy
	} from '../../api/mock'
	export default {
		data() {
			return {
				navList: [], //分类数据
				status: 'loading',
				scrollTop: 0, //每次点击的滚动条位置变量：默认从第一个开始
				oldScrollTop: 0, //上一次点击的滚动条位置
				menuHeight: 0, //整个左侧菜单的高度
				menuItemHeight: 0, //左侧单个菜单的高度
				currentIndex: 0,
				TopArr: [], //根据标签顺序，获取每个section的高度
				scrollRightTop: 0, //右侧菜单的滚动位置变量
			}
		},
		onLoad() {
			this.getClassfy()
		},
		onReady() {
			// 当前页面初次渲染完成后，获取所有section的高度（右侧菜单的）
			this.getMenuItemTopDistance();
		},
		methods: {
			go(){
				uni.navigateTo({
					url:'/page_search/search/search'
				})
			},
			/* 发起请求的函数 */
			getClassfy() {
				apiClassfy().then((res) => {
					this.status = 'nomore';
					this.navList = [...res];
				}).catch((err) => {
					console.log(err)
				})
			},

			/* 工具函数:获取右侧每个子菜单的高度（到顶部的距离） */
			getMenuItemTopDistance() {
				new Promise((resolve) => {
					let query = uni.createSelectorQuery();
					// 从所有section中获取每个节点的布局位置信息
					query.selectAll('.section').boundingClientRect((data) => {
						if (!data.length) {
							setTimeout(() => {
								this.getMenuItemTopDistance()
							}, 20)
							return;
						}
						// 遍历：获取每个section的top坐标，计算出距离第一个置顶的菜单距离
						data.forEach((item) => {
							this.TopArr.push(item.top - data[0].top);
							resolve();
						})
					}).exec()
				})
			},
			/* 工具函数:获取指定标签的整个高度以及单个标题的高度(标签设置为参数:为了让toggleMenu做菜单的定位居中) */
			/* elClass：你想要获取的标签选择器名称 */
			/* dataVal参数:动态给不确定的data变量赋值*/
			getEIRect(elClass, dataVal) {
				new Promise((reslove, reject) => {
					//获取当前传递过来的标签节点对象
					let query = uni.createSelectorQuery().in(this);
					//获取指定标签选择器中的尺寸宽高
					query.select('.' + elClass).fields({
						size: true
					}, (res) => {
						//如果页面渲染加载较慢，有可以标签在此时仍未获取成功
						console.log(res);

						if (!res) {
							setTimeout(() => {
								//过一段时间再次执行本函数即可
								this.getEIRect(elClass);
							}, 20)
							return;
						}
						//将this作为数组,将dataVal作为下标,根据需求，从res内提取所需数据
						this[dataVal] = res.height; //this.menuItemHeight=55
						console.log(this[dataVal]);
					}).exec();
				})
			},


			/* 切换左侧菜单，促使被点击的菜单剧中显示（抛出最开始和最后的菜单） */
			async toggleMenu(index) {
				// 保险机制:当前事件调用工具函数之前，先判断工具函数的返回值/data数据是否已经有结果，如果没有结果，那就需要再次执行工具函数
				if (this.TopArr.length == 0) {
					await this.getMenuItemTopDistance()
				}
				//重复点击
				if (index == this.currentIndex) return;
				// 将上一次获取到的滚动条位置赋值给右侧滚动变量
				this.scrollRightTop = this.oldScrollTop;
				//this.$nextTick():将Dom更新更改时机:洗一次数据更新之后，Dom更新之前
				this.$nextTick(function() {
					// 将本次点击的下标index，从section高度数组中获取对应的元素值并赋值给右侧滚动高度
					this.scrollRightTop = this.TopArr[index];
					//将本次点击的小标，赋值给一次选择下标变量
					this.currentIndex = index;
					//调用滚动动画计算过程
					this.leftMenuStatus(index);
				})


				/* //判断：当前点击的菜单下标跟当前循环的菜单下标是否一致：赋值
				//将当前点击的菜单相关选择器传递过去
				this.getEIRect('tabItem','scrollTop') */
			},
			async leftMenuStatus(index) {
				//将本次点击的下标，赋值给当前选择器样式判断变量
				this.currentIndex = index;
				//如果两个菜单的高度都为0的情况下，表示菜单的高度并未获取
				if (this.menuHeight == 0 || this.menuItemHeight == 0) {
					//获取整个左侧菜单的高度
					await this.getEIRect('leftNav', 'menuHeight');
					//获取单个菜单的高度
					await this.getEIRect('tabItem', 'menuItemHeight');
				}

				//计算出当前所点击的菜单，需要将滚动条设置到那个位置上
				this.scrollTop = index * this.menuItemHeight + this.menuItemHeight / 2 - this.menuHeight / 2;

			},
			/* 右侧滚动事件：触发左侧的动画效果 */
			async rightScroll(e) {
				//将本次的滚动顶点坐标赋值给oldScrollTop
				this.oldScrollTop = e.detail.scrollTop;
				//保险机制:当前事件调用工具函数之前，先判断工具函数的返回值/data数据是否已经有结果，如果没有结果，那就需要再次执行工具函数
				if (this.TopArr.length == 0) {
					await this.getMenuItemTopDistance();
				}
				if (!this.menuHeight) {
					await this.getEIRect('leftNav', 'menuHeight');
				}
				//定时器:节流
				this.timer = setTimeout(() => {
					//延迟定时器启动后，内部清空
					this.timer = null;
					//计算出右侧菜单垂直重点的位置
					let scrollHeight = this.menuHeight / 2 + e.detail.scrollTop;
					//遍历所有section菜单的高度
					for (let i = 0; i < this.TopArr.length; i++) {
						let height1 = this.TopArr[i]; // 当前i的高度：女装section
						let height2 = this.TopArr[i + 1]; //下一个i的高度：美食section
						//还没到最后一个section或者滚动的中间点大于当前section的高度(滚动已经离开了当前菜单) 同时 滚动的中间点小于下一个菜单(下一个菜单还没有滚动完)
						if (!height2 || scrollHeight >= height1 && scrollHeight < height2) {
							this.leftMenuStatus(i);
							return;
						}
					}
				}, 100)
			}
		}
	}
</script>

<style lang="scss" scoped>
	/* calc():计算复杂的公式:根据设备屏幕尺寸计算出目标区域的自适应高度 */
	.wrap {
		height: calc(100vh);
		display: flex;
		flex-direction: column;
		/* #ifdef H5 */
		height: calc(100vh - var(--window-top));
		/* #endif */
	}

	.search {
		padding: 8px 20px;

		.searchInput {
			background-color: rgb(234, 234, 234);
			border-radius: 20px;
			display: flex;
			align-items: center;
			padding: 0 8px;

			.inpuTxt {
				font-size: 14px;
				color: $u-tips-color;
				margin-left: 10px;
			}
		}
	}


	/* 滚动区域样式 */
	.menuwrap {
		background-color: white;
		display: flex;
		flex: 1; //表示：在100vh的基础下，减去搜索框所占的高度，剩余高度由该标签继承
		overflow: hidden; //清除掉页面的滚动条

		//左侧
		.leftNav {
			width: 25%;
			//高度100%的前提是：父级标签有明确高度，100%与父级标签的高度一致【父级标签没有高度时设置高度百分百相当于没有高度】
			height: 100%;

			.tabItem {
				height: 55px;
				background-color: #f6f6f6;
				box-sizing: border-box;
				display: flex;
				align-items: center;
				justify-content: center;
				font-size: 13px;
				color: #444;
				font-weight: 400;

				.line {
					display: flex;
					align-items: center;
					justify-content: center;
					width: 100%;
					height: 100%;

					/* &表示当前所在区域的class选择器.tabItem */
					&.active {
						color: #000;
						font-size: 15px;
						font-weight: 600;
						background-color: white;
						position: relative;

						// ::before伪类：在指定标签之前添加的效果（不用标签包裹的）
						// ::ofter伪类：在指定标签之后添加的效果
						&::before {
							content: "";
							position: absolute;
							height: 16px;
							left: 0;
							top: 19px;
							border: 2px solid #3c9cff;
						}
					}
				}
			}
		}

		//右侧
		.rightNav {

			.pageView {
				padding: 8px;

				.section {
					margin-bottom: 15px;
					padding: 8px;
					border-radius: 4px;

					&:last-child {
						min-height: 100vh;
					}

					.title {
						font-size: 14px;
						color: #303133;
						font-weight: bold;
					}

					.aside {
						display: flex;
						flex-wrap: wrap;

						.li {
							width: 33.3333333%;
							display: flex;
							align-items: center;
							justify-content: center;
							flex-direction: column;
							margin-top: 10px;

							.li-img {
								width: 60px;
								height: 60px;
							}

							.li-name {
								font-weight: normal;
								font-size: 12px;
								color: #303133;
							}
						}
					}
				}
			}
		}
	}
</style>